// ColorContourModel.cpp

# include "ColorContourModel.h"

namespace Voltron
{
	// A global constant for the number of points that will be in our object.
	//const int NumPoints = 21600;
	const int NumPoints = 21600 * 6;
	using namespace std;
	using namespace boost;
	
	ColorContourModel::ColorContourModel()
	{
	        data = readDataSet("salinityCurrent.txt");
	        discreteData = discretizeData(data,20);
	        coolers = discreteToRGB(discreteData,120,180);
	        vertices = makeVertices_1(120,180);
	        //vec3 * vertices = makeVertices(data.size(),data[0].size());
	}

	
	ColorContourModel::ColorContourModel(string filename)
	{
	        data = readDataSet(filename);
	        discreteData = discretizeData(data,20);
	        coolers = discreteToRGB(discreteData,120,180);
	        vertices = makeVertices_1(120,180);
	        //vec3 * vertices = makeVertices(data.size(),data[0].size());
	}

				
	//-----------------------------------------------------------------------
	// Reads those gosh darned .txt files
	// They are #very#emotional
	vector< vector<float> > ColorContourModel::readDataSet(string dataSetText){
	        int m;
	        int n;
	
	        string line;
	        vector <string> data;
	        vector <string> fields;
	        vector < vector <float> > dataMatrix;
	        ifstream dataFile(dataSetText.c_str());
	
	        if(dataFile.is_open())
	        {
	                getline(dataFile,line);
	                split(fields,line,is_any_of(" \n"));
	        }
	
	        m = atoi(fields[1].c_str());
	        n = atoi(fields[2].c_str());
	
	        while(!dataFile.eof())
	        {
	                getline(dataFile,line);
	                split(fields,line,is_any_of(" "));
	                data.insert(data.end(),fields.begin(),fields.end()-1);
	        }
	
	        dataMatrix.resize(n,vector<float>(m));
	        for(int i = 0; i != n; i++)
	        {
	                for(int j = 0; j != m; j++)
	                {
	                dataMatrix[i][j] = atof(data[m*i+j].c_str());
	                }
	        }
	        return dataMatrix;
	}
	//-------------------------------------------------------------------------
	// Does something /discretely/
	vector <vector <int> > ColorContourModel::discretizeData(vector <vector <float> > data, int numBuckets){
	        //accept data matrix
	        //do that crazy function over every value
	        //return matrix of ints
	        float tempLargest = 0;
	        float tempSmallest = 0;
	        float temp = 0;
	
	        for(size_t i = 0; i != data.size()-1;i++)
	        {
	                temp =  *max_element(data[i].begin(),data[i].end());
	                if(temp != 0 && temp > tempLargest)
	                        tempLargest = temp;
	
	                temp =  *min_element(data[i].begin(),data[i].end());
	                if(temp != 0 && temp < tempSmallest)
	                        tempSmallest = temp;
	        }
	
	        vector < vector<int> > bucketMatrix;
	        bucketMatrix.resize(data.size(),vector<int>(data[0].size()));
	
	        for(int i = 0; i != data.size(); i++)
	        {
	                for(int j = 0; j != data[0].size(); j++)
	                {
	                temp = data[i][j];
	                temp == 0 ? bucketMatrix[i][j] = -2 : bucketMatrix[i][j] = (int)((temp-tempSmallest)/(tempLargest-tempSmallest) * (numBuckets - 1) + .5) + 1;
	                }
	        }
	        return bucketMatrix;
	}
	//----------------------------------------------------------------------------
	// the HSV color model will be as follows
	// h : [0 - 360]
	// s : [0 - 1]
	// v : [0 - 1]
	// If you want it differently (in a 2 * pi scale, 256 instead of 1, etc,
	// you'll have to change it yourself.
	// rgb is returned in 0-1 scale (ready for color3f)
	void ColorContourModel::HSVtoRGB(float hsv[3], float rgb[3]) {
		float tmp1 = hsv[2] * (1-hsv[1]);
		float tmp2 = hsv[2] * (1-hsv[1] * (hsv[0] / 60.0f - (int) (hsv[0]/60.0f) ));
		float tmp3 = hsv[2] * (1-hsv[1] * (1 - (hsv[0] / 60.0f - (int) (hsv[0]/60.0f) )));
		switch((int)(hsv[0] / 60)) {
			case 0:
				rgb[0] = hsv[2] ;
				rgb[1] = tmp3 ;
				rgb[2] = tmp1 ;
				break;
			case 1:
				rgb[0] = tmp2 ;
				rgb[1] = hsv[2] ;
				rgb[2] = tmp1 ;
				break;
			case 2:
				rgb[0] = tmp1 ;
				rgb[1] = hsv[2] ;
				rgb[2] = tmp3 ;
				break;
			case 3:
				rgb[0] = tmp1 ;
				rgb[1] = tmp2 ;
				rgb[2] = hsv[2] ;
				break;
			case 4:
				rgb[0] = tmp3 ;
				rgb[1] = tmp1 ;
				rgb[2] = hsv[2] ;
				break;
			case 5:
				rgb[0] = hsv[2] ;
				rgb[1] = tmp1 ;
				rgb[2] = tmp2 ;
				break;
			default:
				cout << "Inconceivable!\n";
	
		}
	
	}
	//----------------------------------------------------------------------------
	// More discretion is required
	vec3 *  ColorContourModel::discreteToRGB(vector< vector<int> > data,int numRows,int numCols){
	        float val = 1.0; //val is mal
	        float sat = 1.0; //With a SAT score this low I'll never get into MIT...
	        float hsv[3];
	        float rgb[3];
	        int scale = 12;
	        vec3 *coolers = new vec3[numRows*numCols*6];
	        vector <float> colors;
	
	        int count = 0;
	
	        for(int i = 0; i != numRows; i++)
	        {
	                for(int j = 0; j != numCols; j++)
	                {
	                   // cout << data[i][j] << endl;
	                        if(data[i][j] != -2){
	                                hsv[0] = (float)(scale*data[i][j]);
	                                hsv[1] = sat;
	                                hsv[2] = val;
	                                HSVtoRGB(hsv,rgb);
	                        }else{
	                                rgb[0] = 1.0;
	                                rgb[1] = 1.0;
	                                rgb[2] = 1.0;
	                        }
	                            coolers[count++] = vec3(rgb[0],rgb[1],rgb[2]);
	                            coolers[count++] = vec3(rgb[0],rgb[1],rgb[2]);
	                            coolers[count++] = vec3(rgb[0],rgb[1],rgb[2]);
	                            coolers[count++] = vec3(rgb[0],rgb[1],rgb[2]);
	                            coolers[count++] = vec3(rgb[0],rgb[1],rgb[2]);
	                            coolers[count++] = vec3(rgb[0],rgb[1],rgb[2]);
	
	                }
	        }
	        /*
	        //cout << colors.size() << " " << NumPoints << "\n";
	        //cout << "stuff works? " << colors.size()/3 << "\n";
	        for (size_t i = 0; i != colors.size()-4; i = i+3)
	        {
	                //cout << i+2 << "\n";
	                rgb[0] = colors[0];
	                rgb[1] = colors[1];
	                rgb[2] = colors[2];
	
	                coolers[6*i] = vec3(rgb[0],rgb[1],rgb[2]);
	                coolers[6*i+1] = vec3(rgb[0],rgb[1],rgb[2]);
	                coolers[6*i+2] = vec3(rgb[0],rgb[1],rgb[2]);
	                coolers[6*i+3] = vec3(rgb[0],rgb[1],rgb[2]);
	                coolers[6*i+4] = vec3(rgb[0],rgb[1],rgb[2]);
	                coolers[6*i+5] = vec3(rgb[0],rgb[1],rgb[2]);
	                cout << i << "\n";
	        }
	        */
	        cout << "I aint broke\n";
	        return coolers;
	}
	
	//----------------------------------------------------------------------------
	// VERTS VERTS IT HURTS
	vec3 * ColorContourModel::makeVertices(int m,int n){
	        vec3 *vertices = new vec3[6*m*n];
	        float tempI = 0;
	        float tempJ = 0;
	        float inverseFloatM = 1.f/(float)m;
	        float inverseFloatN = 1.f/(float)n;
	        int count = 0;
	        float z = -4.0;
	
	        for(int i = 0; i != n; i++)
	        {
	                for(int j = 0; j != m; j++)
	                {
	                        //tempI = (float)i * inverseFloatN - 1.0;
	                        //tempJ = (float)j * inverseFloatM - 1.0;
	                        tempI = (float)i;
	                        tempJ = (float)j;
	                        //cout << tempI << " " << tempJ << "\n";
	                        vertices[count] = vec3(tempI,tempJ,z);
	                        vertices[count+1] = vec3(1+tempI,tempJ,z);
	                        vertices[count+2] = vec3(tempI,1+tempJ,z);
	                        vertices[count+3] = vec3(1+tempI,1+tempJ,z);
	                        vertices[count+4] = vec3(tempI,1+tempJ,z);
	                        vertices[count+5] = vec3(1+tempI,tempJ,z);
	                        count = count + 6;
	                        //cout  << vertices[n*i+6*j+5] << "\n";
	                }
	        }
	        //cout << count << " ";
	        return vertices;
	}
	
	vec2 * ColorContourModel::makeVertices_1(int numRows, int numColumns){
	    vec2 *vertices = new vec2[numRows*numColumns*6];
	    int vecCounter=0;
	
	    for(int i=0; i<numRows; i++){
	        for(int j=0; j<numColumns; j++){
	            float temp1=(float)i;
	            float temp2=(float)j;
	
	            vertices[vecCounter++]=vec2((2*(temp1)/numRows)-1,(2*(temp2+1)/numColumns)-1);
	            vertices[vecCounter++]=vec2((2*(temp1)/numRows)-1,(2*(temp2)/numColumns)-1);
	            vertices[vecCounter++]=vec2((2*(temp1+1)/numRows)-1,(2*(temp2+1)/numColumns)-1);
	            vertices[vecCounter++]=vec2((2*(temp1)/numRows)-1,(2*(temp2)/numColumns)-1);
	            vertices[vecCounter++]=vec2((2*(temp1+1)/numRows)-1,(2*(temp2)/numColumns)-1);
	            vertices[vecCounter++]=vec2((2*(temp1+1)/numRows)-1,(2*(temp2+1)/numColumns)-1);
	
	        }
	    }
	
	
	    return vertices;
	}
}

#endif